#ifndef CLIB_CLIB_CONTAINER_DOUBLE_LINKED_LIST_H
#define CLIB_CLIB_CONTAINER_DOUBLE_LINKED_LIST_H

#include "../../base/clib_base.h"

CLIB_CPLUS_SUPPORT_START

/**
 * 双向链表对象
 */
struct clib_container_double_linked_list;

/**
 * 双向链表配置对象
 */
struct clib_container_double_linked_list_conf {
    /**
    * 内存分配函数
    * @param size 需要分配的大小
    * @return
    */
    void *(*mem_malloc_func)(size_t size);

    /**
     * 内存释放函数
     * @param block 块指针
     */
    void (*mem_free_func)(void *block);

    /**
     * 内存拷贝函数
     * @param target 目标
     * @param src 源
     * @param size 大小
     * @return
     */
    void *(*mem_copy_func)(void *target, const void *src, size_t size);
};

/**
 * 创建一个双向链表
 * @param conf 配置对象
 * @param out 存储创建好的双向链表
 * @return
 * 成功 0
 * 失败 非0
 */
int clib_container_double_linked_list_create_with_conf(
        struct clib_container_double_linked_list_conf *conf,
        struct clib_container_double_linked_list **out);


/**
 * 销毁双向链表
 * @param list 链表对象
 */
void clib_container_double_linked_list_destroy(
        struct clib_container_double_linked_list *list);

/**
 * 删除所有节点，并返回删除后的数据指针
 * @param list 链表对象
 * @param out 删除后的数据指针
 * @return
 * 成功 0
 * 失败 非0
 */
int clib_container_double_linked_list_remove_all(
        struct clib_container_double_linked_list *list,
        void **out);


/**
 * 添加元素到首节点
 * @param list 链表对象
 * @param element 添加的元素
 * @return
 * 成功 0
 * 失败 非0
 */
int clib_container_double_linked_list_add_first(
        struct clib_container_double_linked_list *list,
        void *element);

/**
 * 添加元素到尾节点
 * @param list 链表对象
 * @param element 添加的元素
 * @return
 * 成功 0
 * 失败 非0
 */
int clib_container_double_linked_list_add_last(
        struct clib_container_double_linked_list *list,
        void *element);

/**
 * 添加元素到尾节点
 * @param list 链表对象
 * @param element 添加的元素
 * @return
 * 成功 0
 * 失败 非0
 */
int clib_container_double_linked_list_add(
        struct clib_container_double_linked_list *list,
        void *element);

/**
 * 在指定索引处添加元素
 * @param list 链表对象
 * @param element 添加的元素
 * @param index 添加的索引
 * @return
 * 成功 0
 * 失败 非0
 */
int clib_container_double_linked_list_add_with_index(
        struct clib_container_double_linked_list *list,
        void *element,
        size_t index);

/**
 * 将list2全部元素添加到list1中指定索引处
 * @param list1 链表对象
 * @param list2 链表对象
 * @param index 指定索引
 * @return
 * 成功 0
 * 失败 非0
 */
int clib_container_double_linked_list_add_all_with_index(
        struct clib_container_double_linked_list *list1,
        struct clib_container_double_linked_list *list2,
        size_t index);


/**
 * 将list2全部元素添加到list1中
 * @param list1 链表对象
 * @param list2 链表对象
 * @return
 * 成功 0
 * 失败 非0
 */
int clib_container_double_linked_list_add_all(
        struct clib_container_double_linked_list *list1,
        struct clib_container_double_linked_list *list2);


/**
 * 删除一个元素，并返回删除的元素数据指针
 * @param list 链表对象
 * @param element 要删除的元素指针
 * @param out 删除后的元素数据指针
 * @return
 * 成功 0
 * 失败 非0
 */
int
clib_container_double_linked_list_remove(
        struct clib_container_double_linked_list *list,
        void *element,
        void **out);

/**
 * 删除指定索引的元素，并返回删除的元素数据指针
 * @param list 链表对象
 * @param index 要删除的元素索引
 * @param out 删除后的元素数据指针
 * @return
 * 成功 0
 * 失败 非0
 */
int clib_container_double_linked_list_remove_with_index(
        struct clib_container_double_linked_list *list,
        size_t index,
        void **out);

/**
 * 删除首元素，并返回删除的元素数据指针
 * @param list 链表对象
 * @param out 删除后的元素数据指针
 * @return
 * 成功 0
 * 失败 非0
 */
int clib_container_double_linked_list_remove_first(
        struct clib_container_double_linked_list *list,
        void **out);

/**
 * 删除尾元素，并返回删除的元素数据指针
 * @param list 链表对象
 * @param out 删除后的元素数据指针
 * @return
 * 成功 0
 * 失败 非0
 */
int clib_container_double_linked_list_remove_last(
        struct clib_container_double_linked_list *list,
        void **out);

/**
 * 替换指定索引的元素
 * @param list 链表对象
 * @param element 新元素
 * @param index 要替换的元素索引
 * @param out 替换后的元素数据指针
 * @return
 * 成功 0
 * 失败 非0
 */
int clib_container_double_linked_list_replace_with_index(
        struct clib_container_double_linked_list *list,
        void *element,
        size_t index,
        void **out);

/**
 * 获取首元素
 * @param list 链表对象
 * @param out 查询出的数据指针
 * @return
 * 成功 0
 * 失败 非0
 */
int clib_container_double_linked_list_get_first(
        struct clib_container_double_linked_list *list,
        void **out);

/**
 * 获取尾元素
 * @param list 链表对象
 * @param out 查询出的数据指针
 * @return
 * 成功 0
 * 失败 非0
 */
int clib_container_double_linked_list_get_last(
        struct clib_container_double_linked_list *list,
        void **out);

/**
 * 获取指定索引的元素
 * @param list 链表对象
 * @param index 查询的索引
 * @param out 查询出的数据指针
 * @return
 * 成功 0
 * 失败 非0
 */
int clib_container_double_linked_list_get_with_index(
        struct clib_container_double_linked_list *list,
        size_t index,
        void **out);


/**
 * 翻转链表
 * @param list 链表对象
 */
void clib_container_double_linked_list_reverse(
        struct clib_container_double_linked_list *list);


CLIB_CPLUS_SUPPORT_END

#endif //CLIB_CLIB_CONTAINER_DOUBLE_LINKED_LIST_H
